package xin.nick.system.manager;

import cn.hutool.core.text.CharSequenceUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import xin.nick.common.core.constant.SystemConstants;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.function.Supplier;

/**
 * 自定义动态权限配置权限校验管理器
 * @author Nick
 * @since 2024/2/29
 */
@Component
@RequiredArgsConstructor
public class DynamicAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {

    private final SystemAuthorityManager systemAuthorityManager;
    private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authenticationSupplier, RequestAuthorizationContext requestAuthorizationContext) {
        Authentication authentication = authenticationSupplier.get();

        // 是否通过
        boolean granted = baseGranted(authentication);
        if (!granted) {
            return new AuthorizationDecision(granted);
        }

        // 获取到request
        HttpServletRequest request = requestAuthorizationContext.getRequest();

        // 从数据库中获取当前接口所需的权限
        String needAuthorityKey = systemAuthorityManager.getAuthorityKeyByRequest(request);

        // 没获取到所需参数权限,则直接放行
        if (CharSequenceUtil.isBlank(needAuthorityKey)) {
            return new AuthorizationDecision(granted);
        }

        // 获取当前用户的权限信息
        Collection<? extends GrantedAuthority> authorityList = authentication.getAuthorities();

        // 超管直接放行
        for (GrantedAuthority grantedAuthority : authorityList) {
            if (SystemConstants.ROOT_ROLE.equals(grantedAuthority.getAuthority())) {
                return new AuthorizationDecision(granted);
            }
        }

        // 只要用户权限列表存在所需要的权限就算通过
        granted = authorityList.stream().anyMatch(authority -> antPathMatcher.match(authority.getAuthority(), needAuthorityKey));

        return new AuthorizationDecision(granted);

    }

    /**
     * 基础授权,需要登录之后,且不是匿名用户,才可以
     * @param authentication
     * @return
     */
    private boolean baseGranted(Authentication authentication) {
        return authentication != null && isNotAnonymous(authentication) && authentication.isAuthenticated();
    }

    /**
     * 是非匿名用户
     * @param authentication
     * @return
     */
    private boolean isNotAnonymous(Authentication authentication) {
        return !this.trustResolver.isAnonymous(authentication);
    }
}
